#!/usr/bin/python
# -*- coding: utf-8 -*-

import Ice, IceStorm
import sys, os, thread, random
import threading, time, sched

try:
    HOME = os.environ['ROBOTS']
except KeyError:
    print 'ROBOTS environment variable is not currently defined.'
    sys.exit(0)

SLICE = os.path.join(HOME, 'slice')
FILE = os.path.join(SLICE, 'Robots.ice')
Ice.loadSlice('--all -I/usr/share/slice', ['-I' + SLICE, FILE])

NUMBER = 6
DELAY = 2

import Robots

class AMI_Model_informI (object):

    def ice_response (self):
        pass

    def ice_exception (self, ex):
        pass

class MyThread (threading.Thread):

    def __init__ (self, auctioneer, adapter, seconds = DELAY):

        threading.Thread.__init__(self)
        self.__auctioneer = auctioneer
        self.__adapter = adapter
        self.__seconds = seconds

    def run (self):
        time.sleep(self.__seconds)
        self.__auctioneer.close(self.__adapter)

class AuctioneerI (Robots.Auctioneer):

    def __init__ (self, adapter, signposts):
        
        self.__adapter = adapter
        self.__signposts = {}
        self.__assignments = {}
        self.__timer = None
        self.__mutex = thread.allocate_lock()

        for i in range (0, len(signposts)):
            self.__signposts[i] = signposts[i]
            self.__assignments[i] = None

        self.__currentBids = []
        self.__sch = sched.scheduler(time.time, time.sleep)
        self.__start = False

        # Reference to the topic manager.
        try:
            ## TODO --> change base.
            #base = adapter.getCommunicator().stringToProxy('Robots.IceStorm/TopicManager')
            base = adapter.getCommunicator().stringToProxy('Robots/TopicManager:default -p 10000')
            topicManager = IceStorm.TopicManagerPrx.checkedCast(base)
        except Ice.Exception, ex:
            sys.stdout.write('Invalid TopicManager: ' + str(ex))

        # Team channel.
        try:
            topic = topicManager.retrieve('AgentTeam.1')
        except IceStorm.NoSuchTopic:
            topic = topicManager.create('AgentTeam.1')

        # Get the publisher
        self.__pub = Robots.AgentPrx.uncheckedCast(topic.getPublisher())

    def begin (self, curr = None):
                
        self.publishFreeSignPosts()

    def receiveBid (self, bid, curr):

        self.__mutex.acquire()

        if self.__start == False:
            print 'The auction begins!'
            self.__timer = MyThread(self, curr.adapter)
            self.__timer.start()
            self.__start = True

        self.__currentBids.append(bid)
        self.printBid(bid)

        self.__mutex.release()

    def close (self, adapter):
        
        aux = {}

        print 'The auction finished!'
        for b in self.__currentBids:
            if aux.has_key(b.sp.pos):
                if aux[b.sp.pos].value < b.value:
                    aux[b.sp.pos] = b
            else:
                aux[b.sp.pos] = b

        self.__currentBids = []

        # Close best bids.
        for bb in aux.values():
            for k, v in self.__signposts.iteritems():
                if bb.sp == v:
                    self.__assignments[k] = bb.ag
                    bb.ag.inform_async(AMI_Model_informI(),
                                    Robots.Close(bb.sp))

        # Check if there is free signposts.
        if self.getNumberOfAssignments() <  NUMBER:
            self.__start = False
            self.publishFreeSignPosts()

    def publishFreeSignPosts (self):

        signposts = []
        for k1, v1 in self.__assignments.iteritems():
            if v1 == None:
                signposts.append(self.__signposts[k1])

        if len(signposts) > 0:
            self.__pub.inform_async(AMI_Model_informI(),
                                    Robots.Announcement(signposts))
        else:
            self.__pub.inform_async(AMI_Model_informI(),
                                    Robots.Finish())

    def printBid (self, b):
        print '[' + str(b.sp.pos.x) + ', ' + str(b.sp.pos.y) + ']: ' + str(b.ag) + ' V: ' + str(b.value)

    def getNumberOfAssignments (self):
        n = 0
        for x in self.__assignments.values():
            if x != None:
                n += 1
        return n

    def getLeader (self, signpost, curr = None):

        for k, sp in self.__signposts.iteritems():
            if sp == signpost:
                try:
                    return self.__assignments[k]
                except KeyError:
                    return None
                
        return None
